/*  This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 2.1 of the License, or (at
    your option) any later version.
    For more details, see the GNU Lesser General Public License (www.fsf.org
    or the COPYING file somewhere in the package)
 */

#include "BundleFactory.hh"

/*! @file src/OSGi/BundleFactory.cc
    @brief Class OSGi::BundleFactory (non-inline) methods.
    @author @ref Guillaume_Terrissol
    @date 9th February 2010 - 10th April 2014
    @note This file is distributed under the LGPL license.
    Refer to the file COPYING (or http://www.fsf.org) for more information.
 */

#include "Context.hh"
#include "Signal.hh"

namespace OSGi
{
//------------------------------------------------------------------------------
//                   Bundle Factory : Constructor & destructor
//------------------------------------------------------------------------------

    /*! Defaulted.
     */
    BundleFactory::BundleFactory() = default;


    /*! Defaulted.
     */
    BundleFactory::~BundleFactory() = default;


//------------------------------------------------------------------------------
//                          Bundle Factory : "Factory"
//------------------------------------------------------------------------------

    /*! @copydetails Bundle::Bundle(std::string, int, ContextCPtr)
        @signal Context::bundleInstalled()
     */
    Bundle::Ptr BundleFactory::makeBundle(std::string pFilename, int pId, ContextCPtr pContext) const
    {
        auto    lNew = doMakeBundle(pFilename, pId, pContext);
        OSGI_EMIT pContext->bundleInstalled(lNew);

        return lNew;
    }


    /*! @return A newly created life cycle, set up by the factory (use
                setUp() to customize the cycle)
     */
    LifeCycle::Ptr BundleFactory::makeBundleLifeCycle() const
    {
        auto    lLifeCycle = std::make_shared<LifeCycle>();

        setUp(lLifeCycle);

        return lLifeCycle;
    }


    /*! @param pLifeCycle This bundle life cycle, created by the factory, is
        initialized with states and state changes in this method and its
        reimplementations
        @note Don't forget to call the default implementation to retrieve the
              default bundle life cycle
     */
    void BundleFactory::setUp(LifeCycle::Ptr pLifeCycle) const
    {
        pLifeCycle->declareInitialState(kInstalled);
        pLifeCycle->declareState(kResolved);
        pLifeCycle->declareState(kUninstalled);
        pLifeCycle->declareState(kActive);

        pLifeCycle->declareChange(kUninstall, kInstalled, kUninstalled, &Bundle::uninstall);
        pLifeCycle->declareChange(kResolve,   kInstalled, kResolved,    &Bundle::tryResolve);
        pLifeCycle->declareChange(kStart,     kResolved,  kActive,      &Bundle::start);
        pLifeCycle->declareChange(kStop,      kActive,    kResolved,    &Bundle::stop);
        pLifeCycle->declareChange(kUninstall, kResolved,  kUninstalled, &Bundle::uninstall);
    }


    /*! This methods may be reimplemented in order to instantiate a different
        kind of bundle.
        @param pFilename Filename, with path (either absolute, or relative) of
               the bundle
        @param pId       Id for the new bundle
        @param pContext  Execution context
     */
    Bundle::Ptr BundleFactory::doMakeBundle(std::string pFilename, int pId, ContextCPtr pContext) const
    {
        return std::make_shared<Bundle>(pFilename, pId, pContext, Bundle::Key{});
    }


//------------------------------------------------------------------------------
//                           Additional Documentation
//------------------------------------------------------------------------------

    /*! @class BundleFactory
        Inheriting this class allows building new kinds of bundles, or enhancing
        the bundle life cycle.@n
     */
}
